﻿using System;
using System.Threading;
using System.Reflection;

using Heaven.Graphics;
using Direct3D9 = SlimDX.Direct3D9;
using Slimdx = SlimDX;

namespace Heaven.SlimDX.Graphics
{
    /// <summary>
    /// SlimDX Render target 2D
    /// </summary>
    internal class SlimDXRenderTarget
    {
        #region Атрибуты

        // SlimDX helper to render to a surface
        Direct3D9.Texture renderTarget = null;
        Direct3D9.Surface renderTargetSurface = null;
        Direct3D9.Texture texture = null;
        Direct3D9.Surface textureSurface = null;
        Direct3D9.Surface depthSurface = null;
        Slimdx.Viewport viewport;
        // Graphics device
        Direct3D9.Device device = null;

        #endregion

        #region Свойства

        /// <summary>
        /// Ширина (в пикселях)
        /// </summary>
        public int Width
        {
            get
            {
                return renderTarget.GetLevelDescription(0).Width;
            }
        }

        /// <summary>
        /// Высота (в пикселях)
        /// </summary>
        public int Height
        {
            get { return renderTarget.GetLevelDescription(0).Height; }
        }

        /// <summary>
        /// Формат пикселей текстуры
        /// </summary>
        public Direct3D9.Format Format
        {
            get { return renderTarget.GetLevelDescription(0).Format; }
        }

        /// <summary>
        /// Внутренняя текстура
        /// </summary>
        internal Direct3D9.Texture SlimDXTexture
        {
            get
            {
                return texture;
            }
        }


        #endregion

        #region Инициализация

        internal SlimDXRenderTarget(
            Direct3D9.Device device,
            int width, int height,
            Direct3D9.Format format)
        {
            this.device = device;
            renderTarget = new Direct3D9.Texture(device, width, height, 1, Direct3D9.Usage.RenderTarget, format, Direct3D9.Pool.Default);
            renderTargetSurface = renderTarget.GetSurfaceLevel(0);
            texture = new Direct3D9.Texture(device, width, height, 1, Direct3D9.Usage.RenderTarget, format, Direct3D9.Pool.Default);
            textureSurface = texture.GetSurfaceLevel(0);
            depthSurface = Direct3D9.Surface.CreateDepthStencil(device, width, height, Direct3D9.Format.D24X8, Direct3D9.MultisampleType.None, 0, true);
            viewport = new Slimdx.Viewport(0, 0, width, height);
        }

        #endregion

        #region Methods


        #endregion

        #region Деструктор

        ~SlimDXRenderTarget()
        {
            Dispose();
        }

        internal void Dispose()
        {
            GC.SuppressFinalize(this);
            if (renderTarget != null)
            {
                renderTargetSurface.Dispose();
                renderTarget.Dispose();
            }
            if (depthSurface != null)
            {
                depthSurface.Dispose();
            }
            if (texture != null) 
            {
                textureSurface.Dispose();
                texture.Dispose();
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Begins using this render 
        /// target to render into it
        /// </summary>
        public void BeginRendering()
        {
            device.Viewport = viewport;
            device.DepthStencilSurface = depthSurface;
            device.SetRenderTarget(0, renderTargetSurface);
            device.BeginScene();
        }

        /// <summary>
        /// Ends using this render 
        /// target to render into it
        /// </summary>
        public void EndRendering()
        {
            device.EndScene();
            ResolveToTexture();
        }

        #endregion

        void ResolveToTexture()
        {
            device.StretchRectangle(renderTargetSurface, textureSurface, Direct3D9.TextureFilter.None);
        }

        internal void GetData(byte[] data)
        {
            Direct3D9.Texture feedbackTexture = new Direct3D9.Texture(device, Width, Height, 1, Direct3D9.Usage.Dynamic, Format, Direct3D9.Pool.SystemMemory);
            Direct3D9.Surface feedbackTextureSurface = feedbackTexture.GetSurfaceLevel(0);
            device.GetRenderTargetData(renderTargetSurface, feedbackTextureSurface);
            Slimdx.DataRectangle dataStream = feedbackTexture.LockRectangle(0, Direct3D9.LockFlags.ReadOnly);
            dataStream.Data.Read(data, 0,data.Length);
            feedbackTexture.UnlockRectangle(0);
            feedbackTextureSurface.Dispose();
            feedbackTexture.Dispose();
        }
    }
    /*/// <summary>
    /// SlimDX Render target 2D
    /// </summary>
    internal class XnaRenderTarget
    {
        #region Атрибуты

        // SlimDX helper to render to a surface
        Direct3D9.Surface renderSurface = null;
        Direct3D9.Texture feedbackTexture = null;
        Direct3D9.Surface depthSurface = null;
        Slimdx.Viewport viewport;
        // Graphics device
        Direct3D9.Device device = null;

        #endregion

        #region Свойства

        /// <summary>
        /// Ширина (в пикселях)
        /// </summary>
        public int Width
        {
            get
            {
                return renderSurface.Description.Width;
            }
        }

        /// <summary>
        /// Высота (в пикселях)
        /// </summary>
        public int Height
        {
            get { return renderSurface.Description.Height; }
        }

        /// <summary>
        /// Формат пикселей текстуры
        /// </summary>
        public Direct3D9.Format Format
        {
            get { return renderSurface.Description.Format; }
        }

        /// <summary>
        /// Внутренняя текстура
        /// </summary>
        internal Direct3D9.Texture SlimDXTexture
        {
            get
            {
                return feedbackTexture;
            }
        }


        #endregion

        #region Инициализация

        internal XnaRenderTarget(
            Direct3D9.Device device,
            int width, int height,
            Direct3D9.Format format)
        {
            this.device = device;
            renderSurface = Direct3D9.Surface.CreateRenderTarget(device, width, height, format, Direct3D9.MultisampleType.None, 0, false);
            feedbackTexture = new Direct3D9.Texture(device, width, height, 1, Direct3D9.Usage.Dynamic, format, Direct3D9.Pool.Default);
            depthSurface = Direct3D9.Surface.CreateDepthStencil(device, width, height, Direct3D9.Format.D24X8, Direct3D9.MultisampleType.None, 0, true);
            viewport = new Slimdx.Viewport(0, 0, width, height);
        }

        #endregion

        #region Methods


        #endregion

        #region Деструктор

        ~XnaRenderTarget()
        {
            Dispose();
        }

        internal void Dispose()
        {
            GC.SuppressFinalize(this);
            renderSurface.Dispose();
            depthSurface.Dispose();
            feedbackTexture.Dispose();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Begins using this render 
        /// target to render into it
        /// </summary>
        public void BeginRendering()
        {
            device.Viewport = viewport;
            device.DepthStencilSurface = depthSurface;
            device.SetRenderTarget(0, renderSurface);
            device.BeginScene();
        }

        /// <summary>
        /// Ends using this render 
        /// target to render into it
        /// </summary>
        public void EndRendering()
        {
            device.EndScene();
            device.StretchRectangle(renderSurface, feedbackTexture.GetSurfaceLevel(0), Direct3D9.TextureFilter.None);
        }

        #endregion
    }*/
}
